Add a user-facing Cancel control for the scenario Open-from-folder scan - #666
Merged
Conversation
…an (#656) The scenario "Open from folder" scan (folder enumeration plus a parallel per-file channel probe) was only cancellable by disposing the dashboard. This adds a persistent masthead status chip that surfaces the scan and a Cancel control that stays reachable regardless of which scenario or category tab is selected. Service (ScenarioLaunchService): LaunchFromFolderAsync gains an optional Func<ScenarioFolderPhase, Task>? onPhase callback (defaulted null, so existing callers are unaffected). It reports Scanning once the picker returns a folder (cancellation is only meaningful from that point) and Opening once a nonempty match commits to opening logs, with a cancellation recheck after the callback so a cancel that lands during the commit still wins before any filter dispatch or log open. Dashboard (EmptyStateDashboard): a per-launch CancellationTokenSource linked to the component lifetime, a three-state masthead chip (Scanning with Cancel, Cancelling..., Opening logs...), focus management that keeps the Cancel button reachable and never strands keyboard focus on the document body, and guarded rendering so the busy state is reflected on the banner-retry path (which runs outside the dashboard event loop). The reactive-launch banner "Open from folder" retry is routed through the guarded wrapper so it no longer bypasses the busy guard. Tests: service-level phase-emission tests (Scanning/Opening boundaries and cancellation) plus bUnit tests covering chip visibility, decoupling from selection, cancellation acknowledgement, the Opening relabel, and the banner-retry busy-state regression.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a user-visible, masthead-level progress/cancel affordance for the “Open from folder” scenario scan, enabling in-place cancellation without disposing the dashboard. This is implemented by plumbing scan phase notifications from the runtime launch service into the dashboard so UI state (chip text, Cancel availability, focus restoration, and busy-guards) remains consistent even when the scan is initiated from non-standard paths (e.g., banner retry).
Changes:
- Extend
ScenarioLaunchService.LaunchFromFolderAsyncwith an optionalonPhasecallback and introduceScenarioFolderPhaseto reportScanning/Openingboundaries (with cancellation re-check before committing). - Add a persistent masthead “Scanning/Cancelling/Opening” chip with a Cancel control, per-launch linked
CancellationTokenSource, and explicit focus management inEmptyStateDashboard. - Add/adjust unit tests (runtime + bUnit UI) to cover phase emission boundaries, cancellation behavior, chip visibility/labeling, and banner-retry busy-guarding.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Unit/EventLogExpert.UI.Tests/Dashboard/EmptyStateDashboardTests.cs | Adds bUnit coverage for the masthead scan chip states, Cancel behavior, focus/busy guarding, and banner-retry path. |
| tests/Unit/EventLogExpert.Runtime.Tests/Scenarios/ScenarioLaunchServiceTests.cs | Adds runtime coverage for phase reporting boundaries and cancellation timing (incl. cancel during Opening). |
| src/EventLogExpert.UI/Dashboard/EmptyStateDashboard.razor.css | Styles the new scan chip accent to distinguish it from the existing filter-applied chip. |
| src/EventLogExpert.UI/Dashboard/EmptyStateDashboard.razor.cs | Implements per-launch cancellation, guarded rendering for non-event-loop triggers, and focus restoration logic. |
| src/EventLogExpert.UI/Dashboard/EmptyStateDashboard.razor | Renders the masthead chip and Cancel button during the scanning window; makes the dashboard root focusable for safe focus fallback. |
| src/EventLogExpert.Runtime/Scenarios/ScenarioLaunchService.cs | Adds onPhase callback support, emits Scanning after picker success, emits Opening only when committing to open, and rechecks cancellation after callback. |
| src/EventLogExpert.Runtime/Scenarios/ScenarioFolderPhase.cs | Introduces the phase enum used by callers to drive user-visible scan state. |
| src/EventLogExpert.Runtime/Scenarios/IScenarioLaunchService.cs | Updates the service contract and documentation to include the optional onPhase callback. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
jschick04
marked this pull request as ready for review
July 24, 2026 01:37
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #656.
Problem
The scenario "Open from folder" scan (folder enumeration plus a parallel per-file channel probe) was only cancellable by disposing the dashboard. There was no busy/progress indicator or Cancel control, and for large or network folders the scan can take a noticeable amount of time.
Approach (persistent masthead Cancel chip)
A status chip in the dashboard masthead surfaces the scan and a Cancel control, driven by a dashboard field so it stays reachable regardless of which scenario or category tab is selected. It has three states:
<scenario>folder for logs... + Cancel<scenario>... (after Cancel, while the in-flight probe drains)<scenario>... (past the commit boundary; no Cancel, because the open is not cancellable)Browsing the scenario list and switching category tabs stay enabled; only the launch actions are busy-disabled, so there is no double-launch risk.
Changes
Service (
ScenarioLaunchService)LaunchFromFolderAsyncgains an optionalFunc<ScenarioFolderPhase, Task>? onPhase(defaulted null, so existing callers are unaffected).Scanningonce the picker returns a folder (cancellation is only meaningful from that point) andOpeningonce a nonempty match commits to opening logs, gated soOpeningis never reported for an outcome that opens nothing.Dashboard (
EmptyStateDashboard)CancellationTokenSourcelinked to the component lifetime.Testing